package org.example.myleet.p838;

public class Solution {
    /**
     * 双指针模拟法，找出...L、R...L、...R、R...的每一段区间（左右指针囊括的位置区间），分类讨论
     */
    public String pushDominoes(String dominoes) {
        char[] dominoesArr = dominoes.toCharArray();
        StringBuilder result = new StringBuilder();
        //l左指针，curIdx右指针，m左指针和右指针的中间位置
        int n = dominoesArr.length, curIdx = 0, l = curIdx, m;
        //右指针指向的字符
        char curChar;
        //中间位置是否站立不倒
        boolean midStand;
        while (curIdx < n) {
            curChar = dominoesArr[curIdx];
            if (curChar == 'L') {
                //考虑右指针是L的情况
                if (dominoesArr[l] == '.' || dominoesArr[l] == 'L') {
                    //当左指针是.或L时，说明区间是清一色往左边倒
                    for (int i = l; i <= curIdx; ++i) {
                        result.append('L');
                    }
                } else {
                    //当左指针是R时，说明区间是左侧的往右倒，右侧的往左倒，奇数时中间站立，偶数时没有站立的骨牌
                    midStand = ((curIdx - l + 1) & 1) == 1;
                    m = (l + curIdx) >>> 1;
                    for (int i = l; i <= curIdx; ++i) {
                        if (i < m) {
                            //左侧的往右倒
                            result.append('R');
                        } else if (i > m) {
                            //右侧的往左倒
                            result.append('L');
                        } else {
                            if (midStand) {
                                //奇数时中间站立
                                result.append('.');
                            } else {
                                //偶数时没有站立的骨牌
                                result.append('R');
                            }
                        }
                    }
                }
                //右指针是L时需要重置左指针，因为当前区间已经找到答案
                l = curIdx + 1;
            } else if (curChar == 'R') {
                if (curIdx > 0) {
                    //考虑右指针是R的情况
                    if (dominoesArr[l] == '.') {
                        //左指针到右指针之间的都是站立的
                        for (int i = l; i < curIdx; ++i) {
                            result.append('.');
                        }
                    } else if (dominoesArr[l] == 'R') {
                        //左指针到右指针之间都往右倒
                        for (int i = l; i < curIdx; ++i) {
                            result.append('R');
                        }
                    }
                    //右指针是R时需要重置左指针，因为当前区间已经找到答案
                    l = curIdx;
                }
            }
            ++curIdx;
        }
        //左指针未完成遍历，表示仍有一部分，此时左指针只可能为.或R
        if (l < n) {
            if (dominoesArr[l] == '.') {
                //左指针为.时，剩余的骨牌全部站立
                for (int i = l; i < n; ++i) {
                    result.append('.');
                }
            } else {
                //左指针为R时，剩余的骨牌全部往右侧倒
                for (int i = l; i < n; ++i) {
                    result.append('R');
                }
            }
        }
        return result.toString();
    }
}
